import React, { useState, useRef, useCallback } from 'react'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import FileUploadButton from '@/components/FileUploadButton'
import { Mic, StopCircle } from 'lucide-react'
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
} from '@/components/ui/form'

import { useForm, SubmitHandler } from 'react-hook-form'
import { Toast } from '@/hooks/use-toast'
import { useVideoStore } from '@/stores/video'
import { uploadService } from '@/services'
import { cn } from '@/lib/utils'

interface AudioSettingsProps {
  cancelClick?: () => void
  onSubmit: (cloneId: string) => void
}

interface FormData {
  chineseText: string
  englishText: string
}

interface CachedStates {
  upload: {
    file: File | null
    url: string
  }
  record: {
    file: File | null
    url: string
    audio: Blob | null
  }
}

const DeclarationForm: React.FC<AudioSettingsProps> = ({
  cancelClick = () => {},
  onSubmit,
}) => {
  const [selectedFile, setSelectedFile] = useState<File | null>(null)
  const { cloneStore, fetchToneList } = useVideoStore()
  const [fileUrl, setFileUrl] = useState('')

  // 添加录音相关状态
  const [audioSourceType, setAudioSourceType] = useState<'upload' | 'record'>(
    'upload',
  )
  const [isRecording, setIsRecording] = useState<boolean>(false)
  const [recordedAudio, setRecordedAudio] = useState<Blob | null>(null)
  const mediaRecorderRef = useRef<MediaRecorder | null>(null)
  const audioChunksRef = useRef<Blob[]>([])

  // 添加缓存状态
  const [cachedStates, setCachedStates] = useState<CachedStates>({
    upload: {
      file: null,
      url: '',
    },
    record: {
      file: null,
      url: '',
      audio: null,
    },
  })

  const form = useForm<FormData>({
    defaultValues: {
      chineseText: '',
      englishText: '',
    },
  })

  // 辅助函数：写入字符串到 DataView
  const writeString = useCallback(
    (view: DataView, offset: number, string: string) => {
      for (let i = 0; i < string.length; i++) {
        view.setUint8(offset + i, string.charCodeAt(i))
      }
    },
    [],
  )

  // 添加音频缓冲区转 WAV 的函数
  const audioBufferToWav = useCallback(
    (buffer: AudioBuffer): Blob => {
      const numberOfChannels = 1
      const length = buffer.length * numberOfChannels * 2
      const data = new DataView(new ArrayBuffer(44 + length))

      // WAV 文件头
      writeString(data, 0, 'RIFF')
      data.setUint32(4, 36 + length, true)
      writeString(data, 8, 'WAVE')
      writeString(data, 12, 'fmt ')
      data.setUint32(16, 16, true)
      data.setUint16(20, 1, true)
      data.setUint16(22, numberOfChannels, true)
      data.setUint32(24, buffer.sampleRate, true)
      data.setUint32(28, buffer.sampleRate * numberOfChannels * 2, true)
      data.setUint16(32, numberOfChannels * 2, true)
      data.setUint16(34, 16, true)
      writeString(data, 36, 'data')
      data.setUint32(40, length, true)

      // 写入音频数据
      const channelData = buffer.getChannelData(0)
      let offset = 44
      for (let i = 0; i < channelData.length; i++) {
        const sample = Math.max(-1, Math.min(1, channelData[i]))
        data.setInt16(offset, sample < 0 ? sample * 0x8000 : sample * 0x7fff, true)
        offset += 2
      }

      return new Blob([data], { type: 'audio/wav' })
    },
    [writeString],
  )

  // 添加音频数据验证函数
  const validateAudioData = useCallback((audioBlob: Blob): Promise<Blob> => {
    return new Promise((resolve, reject) => {
      const reader = new FileReader()

      reader.onload = async () => {
        try {
          if (reader.result instanceof ArrayBuffer) {
            if (reader.result.byteLength === 0) {
              throw new Error('Empty audio data')
            }
            const validBlob = new Blob([reader.result], { type: 'audio/wav' })
            resolve(validBlob)
          } else {
            throw new Error('Invalid audio data format')
          }
        } catch (error) {
          reject(error)
        }
      }

      reader.onerror = () => reject(new Error('Failed to read audio data'))
      reader.readAsArrayBuffer(audioBlob)
    })
  }, [])

  // 添加音频格式转换函数
  const convertToWav = useCallback(
    async (blob: Blob): Promise<Blob> => {
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = async () => {
          try {
            const AudioContextClass =
              window.AudioContext || (window as any).webkitAudioContext
            const audioContext = new AudioContextClass()
            const audioBuffer = await audioContext.decodeAudioData(
              reader.result as ArrayBuffer,
            )

            const offlineContext = new OfflineAudioContext(
              1,
              audioBuffer.length,
              audioBuffer.sampleRate,
            )

            const source = offlineContext.createBufferSource()
            source.buffer = audioBuffer
            source.connect(offlineContext.destination)
            source.start()

            const renderedBuffer = await offlineContext.startRendering()
            const wavBlob = audioBufferToWav(renderedBuffer)
            resolve(wavBlob)
          } catch (error) {
            reject(error)
          }
        }
        reader.onerror = () => reject(new Error('Failed to read audio file'))
        reader.readAsArrayBuffer(blob)
      })
    },
    [audioBufferToWav],
  )

  // 修改切换按钮的处理函数
  const handleSourceTypeChange = useCallback(
    (type: 'upload' | 'record') => {
      // 保存当前状态到缓存
      if (audioSourceType === 'upload') {
        setCachedStates((prev) => ({
          ...prev,
          upload: {
            file: selectedFile,
            url: fileUrl,
          },
        }))
      } else {
        setCachedStates((prev) => ({
          ...prev,
          record: {
            file: selectedFile,
            url: fileUrl,
            audio: recordedAudio,
          },
        }))
      }

      // 切换类型
      setAudioSourceType(type)

      // 恢复缓存的状态
      if (type === 'upload') {
        setSelectedFile(cachedStates.upload.file)
        setFileUrl(cachedStates.upload.url)
        setRecordedAudio(null)
      } else {
        setSelectedFile(cachedStates.record.file)
        setFileUrl(cachedStates.record.url)
        setRecordedAudio(cachedStates.record.audio)
      }
    },
    [audioSourceType, selectedFile, fileUrl, recordedAudio, cachedStates],
  )

  // 修改文件上传处理
  const handleFileUpload = useCallback((fileUrl: string, file?: File) => {
    if (!file) return

    // 更新当前状态
    setSelectedFile(file)
    setFileUrl(fileUrl)

    // 同时更新缓存状态
    setCachedStates((prev) => ({
      ...prev,
      upload: {
        file: file,
        url: fileUrl,
      },
    }))
  }, [])

  // 修改录音相关函数
  const startRecording = async () => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({
        audio: {
          channelCount: 1,
          sampleRate: 44100,
          echoCancellation: true,
          noiseSuppression: true,
        },
      })

      mediaRecorderRef.current = new MediaRecorder(stream, {
        mimeType: 'audio/webm;codecs=opus',
        bitsPerSecond: 128000,
      })

      audioChunksRef.current = []

      mediaRecorderRef.current.ondataavailable = (event) => {
        if (event.data.size > 0) {
          audioChunksRef.current.push(event.data)
        }
      }

      mediaRecorderRef.current.onstop = async () => {
        try {
          const audioBlob = new Blob(audioChunksRef.current, { type: 'audio/webm' })

          // 验证音频数据
          const validatedBlob = await validateAudioData(audioBlob)

          // 转换为 WAV 格式
          const wavBlob = await convertToWav(validatedBlob)

          const audioFile = new File([wavBlob], `recorded_audio_${Date.now()}.wav`, {
            type: 'audio/wav',
          })
          const audioUrl = URL.createObjectURL(wavBlob)

          // 更新当前状态
          setRecordedAudio(wavBlob)
          setSelectedFile(audioFile)
          setFileUrl(audioUrl)

          // 同时更新缓存状态
          setCachedStates((prev) => ({
            ...prev,
            record: {
              file: audioFile,
              url: audioUrl,
              audio: wavBlob,
            },
          }))

          // 停止所有音轨
          stream.getTracks().forEach((track) => track.stop())
        } catch (error) {
          console.error('Error processing audio:', error)
          Toast.show({
            content: '音频处理失败',
            icon: 'error',
          })
        }
      }

      // 每 1 秒收集一次数据
      mediaRecorderRef.current.start(1000)
      setIsRecording(true)
    } catch (error) {
      console.error('Error starting recording:', error)
      Toast.show({
        content: '无法访问麦克风',
        icon: 'error',
      })
    }
  }

  const stopRecording = () => {
    if (mediaRecorderRef.current && isRecording) {
      try {
        mediaRecorderRef.current.requestData()
        mediaRecorderRef.current.stop()
        setIsRecording(false)
      } catch (error) {
        console.error('Error stopping recording:', error)
        Toast.show({
          content: '停止录音失败',
          icon: 'error',
        })
      }
    }
  }

  const handleSubmit: SubmitHandler<FormData> = async (data) => {
    if (!data.chineseText || !data.englishText) {
      Toast.show({
        content: '请输入中文和英文文本',
        icon: 'error',
      })
      return
    }

    if (!selectedFile || !fileUrl) {
      Toast.show({
        content: '请选择或录制音频文件',
        icon: 'error',
      })
      return
    }

    try {
      // 如果是录制的音频，需要先上传
      let finalFileUrl = fileUrl
      if (audioSourceType === 'record' && selectedFile) {
        Toast.show({
          content: '正在上传音频文件...',
          icon: 'loading',
        })

        // 使用uploadService上传文件
        const result = await uploadService.uploadFile(selectedFile, (progress) => {
          console.log(`上传进度: ${progress}%`)
        })

        if (!result?.url) {
          throw new Error('音频上传失败')
        }

        finalFileUrl = result.url
      }

      // 调用克隆接口
      const res = await cloneStore({
        names: {
          zh: data.chineseText,
          en: data.englishText,
        },
        url: finalFileUrl,
      })

      await fetchToneList(true)

      if (res?.id !== undefined) {
        onSubmit(res.id + '')
      }
    } catch (error) {
      console.error('提交失败:', error)
      Toast.show({
        content: '提交失败，请重试',
        icon: 'error',
      })
    }
  }

  return (
    <Card className="w-full border-none bg-transparent">
      <CardHeader className="p-0 pb-2.5">
        <CardTitle className="text-lg font-ak font-medium">Clone Sound</CardTitle>
      </CardHeader>
      <CardContent className="p-0">
        <Form {...form}>
          <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4">
            <FormField
              control={form.control}
              name="chineseText"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>
                    Chinese Text:
                    <span className="ml-1">
                      <svg
                        viewBox="0 0 24 24"
                        className="w-4 h-4 inline-block"
                        fill="none"
                        stroke="currentColor"
                      >
                        <circle cx="12" cy="12" r="10" strokeWidth="2" />
                        <path
                          d="M12 16v-4M12 8h.01"
                          strokeWidth="2"
                          strokeLinecap="round"
                        />
                      </svg>
                    </span>
                  </FormLabel>
                  <FormControl>
                    <Input
                      placeholder="Please enter Chinese text"
                      {...field}
                      className="bg-white/5 border-none placeholder:text-white/40"
                    />
                  </FormControl>
                </FormItem>
              )}
            />

            <FormField
              control={form.control}
              name="englishText"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>English Text:</FormLabel>
                  <FormControl>
                    <Input
                      placeholder="Please enter English text"
                      {...field}
                      className="bg-white/5 border-none placeholder:text-white/40"
                    />
                  </FormControl>
                </FormItem>
              )}
            />

            <div className="space-y-2">
              <Label>Audio Clip:</Label>
              <div className="flex flex-col gap-4">
                {/* 添加音频来源选择按钮 */}
                <div className="flex gap-4">
                  <Button
                    type="button"
                    variant="outline"
                    // variant={audioSourceType === 'upload' ? 'default' : 'outline'}
                    className={cn(
                      'flex-1 rounded-[10px] h-[38px] border-transparent hover:bg-[#A091FD]/20 text-white/80 font-ak text-sm font-normal',
                      audioSourceType === 'upload'
                        ? 'bg-black/40 border-[#A091FD]'
                        : 'bg-[#A091FD]/10 text-white/80',
                    )}
                    onClick={() => handleSourceTypeChange('upload')}
                  >
                    Upload from local
                  </Button>
                  <Button
                    type="button"
                    variant="outline"
                    // variant={audioSourceType === 'record' ? 'default' : 'outline'}
                    className={cn(
                      'flex-1 rounded-[10px] h-[38px] border-transparent hover:bg-[#A091FD]/20 text-white/80 font-ak text-sm font-normal',
                      audioSourceType === 'record'
                        ? 'bg-black/40 border-[#A091FD]'
                        : 'bg-[#A091FD]/10 text-white/80',
                    )}
                    onClick={() => handleSourceTypeChange('record')}
                  >
                    Record in real time
                  </Button>
                </div>

                {/* 根据音频来源类型显示不同的内容 */}
                {audioSourceType === 'upload' ? (
                  <FileUploadButton
                    className="h-[38px] text-center w-full"
                    onUpload={handleFileUpload}
                    useLoading={true}
                    accept="audio/*"
                    maxSize={10 * 1024 * 1024}
                  >
                    <Button
                      type="button"
                      variant="outline"
                      className="w-full h-[38px] rounded-[10px] border-none hover:bg-white/10 text-[#A091FD] bg-white/5"
                    >
                      Select file
                    </Button>
                  </FileUploadButton>
                ) : (
                  <div className="flex flex-col gap-2">
                    <Button
                      type="button"
                      variant="outline"
                      // variant={isRecording ? 'destructive' : 'secondary'}
                      className={cn(
                        'w-full h-[38px] rounded-[10px] border-none flex items-center justify-center gap-2',
                        isRecording
                          ? 'hover:bg-destructive/80 bg-destructive border-transparent text-white'
                          : 'hover:bg-white/10 text-[#A091FD] bg-white/5',
                      )}
                      onClick={isRecording ? stopRecording : startRecording}
                    >
                      {isRecording ? (
                        <>
                          <StopCircle className="h-4 w-4" />
                          Stop recording
                        </>
                      ) : (
                        <>
                          <Mic className="h-4 w-4" />
                          Start recording
                        </>
                      )}
                    </Button>
                    {recordedAudio && (
                      <div className="py-2">
                        <audio
                          src={URL.createObjectURL(recordedAudio)}
                          controls
                          className="w-full"
                        />
                      </div>
                    )}
                  </div>
                )}
              </div>
              {selectedFile && (
                <div className="text-sm text-white/60 font-ak font-normal">
                  Selected: {selectedFile.name}
                </div>
              )}
            </div>

            <div className="flex gap-2 pt-4 px-6">
              {/* <Button onClick={cancelClick} type="button" variant="outline">
                Cancel
              </Button> */}
              <Button
                type="submit"
                className="w-full h-11 rounded-full font-ak font-medium text-base"
              >
                Confirm
              </Button>
            </div>
          </form>
        </Form>
      </CardContent>
    </Card>
  )
}

export default DeclarationForm
